﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Linq;
using PokemonBattle.PokemonData;

namespace PokemonBattle.PokemonData.Util
{
    public static class PokemonValidator
    {
        #region 6D

        public static bool ValidateIv(this Base6D iv)
        {
            return !iv.Any((p) => p < 0 && p > 31);
        }

        public static bool ValidateEv(this Base6D ev)
        {
            return !ev.Any((p) => p < 0 && p > 255) && ev.Sum() <= 510;
        }

        #endregion

        #region Check

        private static string FalseMove1, FalseMove2;

        public static bool CheckPokemon(this PokemonCustomInfo pokemon)
        {
            var pokemonData = BattleData.GetPokemon(pokemon.Identity);
            Trait trait = pokemon.SelectedTrait == 1 ? pokemonData.Trait1 : pokemonData.Trait2;
            if (pokemonData == null || trait == Trait.无 || BattleData.PokemonIsRemoved(pokemon.Identity)) return false;

            List<string> moveDatas = new List<string>();
            foreach (string str in pokemon.SelectedMoves)
            {
                if (str != "")
                {
                    if (pokemonData.GetMove(str) == null || pokemonData.GetMove(str).WithoutTrait == trait)
                    {
                        return false;
                    }
                    moveDatas.Add(str);
                }
            }
            return CheckMoves(moveDatas, pokemonData, null);
        }

        public static List<PokemonData> GetEggGroup(EggGroup eggGroup, List<EggGroup> exceptList)
        {
            return (from PokemonData pm in BattleData.GetAllPokemons()
                    where ((pm.EggGroup1 == eggGroup && !exceptList.Contains(pm.EggGroup2)) ||
                    (pm.EggGroup2 == eggGroup && !exceptList.Contains(pm.EggGroup1))) &&
                    pm.GenderRestriction != PokemonGenderRestriction.FemaleOnly &&
                    pm.GenderRestriction != PokemonGenderRestriction.NoGender
                    select pm).ToList();
            //List<PokemonData> array = new List<PokemonData>();
            //foreach (var pm in BattleData.GetAllPokemons())
            //{
            //    if ((pm.EggGroup1 == eggGroup && !exceptList.Contains(pm.EggGroup2)) || (pm.EggGroup2 == eggGroup && !exceptList.Contains(pm.EggGroup1)))
            //    {
            //        if (pm.GenderRestriction != PokemonGenderRestriction.FemaleOnly && pm.GenderRestriction != PokemonGenderRestriction.NoGender)
            //        {
            //            array.Add(pm);
            //        }
            //    }
            //}
            //return array;
        }

        private static List<PokemonData> GetEggGroup(EggGroup eggGroup, PokemonData except)
        {
            List<PokemonData> array = new List<PokemonData>();
            if (except.Number == 236 || except.BeforeEvolution == 236)
            {
                array.Add(BattleData.GetPokemon(106));
                array.Add(BattleData.GetPokemon(107));
                array.Add(BattleData.GetPokemon(236));
                array.Add(BattleData.GetPokemon(237));
                array.Remove(except);
            }
            else
            {
                foreach (PokemonData pm in BattleData.GetAllPokemons())
                {
                    if ((pm.EggGroup1 == eggGroup || pm.EggGroup2 == eggGroup) && !object.ReferenceEquals(pm, except))
                    {
                        if (pm.GenderRestriction != PokemonGenderRestriction.FemaleOnly && pm.GenderRestriction != PokemonGenderRestriction.NoGender)
                        {
                            array.Add(pm);
                        }
                    }
                }
            }
            return array;
        }

        public static List<PokemonData> GetPMs(string move1, string move2, List<PokemonData> list)
        {
            List<PokemonData> array = new List<PokemonData>();
            foreach (PokemonData pm in list)
            {
                if (pm.GetMove(move1) != null && pm.GetMove(move2) != null)
                {
                    array.Add(pm);
                }
            }
            return array;
        }

        public static List<PokemonData> GetPMs(List<string> moves, List<PokemonData> list)
        {
            var array = from PokemonData pm in list
                        where !moves.Exists(m => pm.GetMove(m) == null)
                        select pm;
            return array.ToList();
        }

        public static bool CheckMoves(List<string> MoveDatas, PokemonData pm, List<EggGroup> exceptList = null)
        {
            List<string> inheritList = new List<string>();
            foreach (string move in MoveDatas)
            {
                if (pm.GetMove(move).LearnBy == "遗传")
                    inheritList.Add(move);
            }
            if (inheritList.Count > 2)
            {
                if (!CanInheritMoves(inheritList, pm, exceptList))
                {
                    string str = "";
                    for (int i = 0; i <= inheritList.Count - 2; i++)
                    {
                        if (i > 0)
                        {
                            str += "," + BattleData.GetMove(inheritList[i]).Name;
                        }
                        else
                        {
                            str += BattleData.GetMove(inheritList[i]).Name;
                        }
                    }
                    FalseMove2 = str;
                    FalseMove1 = BattleData.GetMove(inheritList[inheritList.Count - 1]).Name;
                    return false;
                }
            }
            for (int i = 0; i <= MoveDatas.Count - 2; i++)
            {
                for (int j = i + 1; j <= MoveDatas.Count - 1; j++)
                {
                    if (!CheckMoves(MoveDatas[i], MoveDatas[j], pm, exceptList))
                    {
                        FalseMove1 = BattleData.GetMove(MoveDatas[i]).Name;
                        FalseMove2 = BattleData.GetMove(MoveDatas[j]).Name;
                        return false;
                    }
                }
            }

            return true;
        }

        private static bool CheckMoves(string move1, string move2, PokemonData pm, List<EggGroup> exceptList = null)
        {
            MoveLearnData moveData1 = default(MoveLearnData);
            MoveLearnData moveData2 = default(MoveLearnData);
            moveData1 = pm.GetMove(move1);
            moveData2 = pm.GetMove(move2);

            string learnby1 = null;
            string learnby2 = null;
            learnby1 = moveData1.LearnBy;
            learnby2 = moveData2.LearnBy;

            if (learnby1 == "遗传" && learnby2 == "未进化")
            {
                if (moveData2.Info == "旧版")
                {
                    return CheckMoves(move1, move2, BattleData.GetPokemon(pm.BeforeEvolution));
                }
            }
            else if (learnby2 == "遗传" && learnby1 == "未进化")
            {
                if (moveData1.Info == "旧版")
                {
                    return CheckMoves(move1, move2, BattleData.GetPokemon(pm.BeforeEvolution));
                }
            }
            else if (learnby1 == "遗传" && learnby2 == "旧版")
            {
                if (moveData1.Info == "DSOnly" || moveData2.Info == "GC")
                {
                    return false;
                }
            }
            else if (learnby2 == "遗传" && learnby1 == "旧版")
            {
                if (moveData2.Info == "DSOnly" || moveData1.Info == "GC")
                {
                    return false;
                }
            }
            else if (learnby1 == "未进化" && learnby2 == "未进化")
            {
                if (pm.NameBase == "鬼蝉")
                {
                    if (BattleData.GetPokemon(pm.BeforeEvolution).GetMove(move1) == null && BattleData.GetPokemon(pm.BeforeEvolution).GetMove(move2) == null)
                    {
                        return CheckNijiaMoveDatas(move1, move2, pm);
                    }
                }
                else
                {
                    return CheckMoves(move1, move2, BattleData.GetPokemon(pm.BeforeEvolution));
                }
            }
            else if (learnby1 == "遗传" && learnby2 == "遗传")
            {
                return CanInheritMoves(move1, move2, pm, exceptList);
            }
            else if (learnby1 == "NPC" && learnby2 == "遗传")
            {
                return false;
            }
            else if (learnby2 == "NPC" && learnby1 == "遗传")
            {
                return false;
            }
            return true;
        }

        private static bool CanInheritMoves(string move1, string move2, PokemonData pm, List<EggGroup> exceptList)
        {

            if (pm.EggGroup1 == EggGroup.陆上 || pm.EggGroup2 == EggGroup.陆上)
                return true;
            if (exceptList == null)
                exceptList = new List<EggGroup>();

            if (exceptList.Contains(pm.EggGroup1) && (exceptList.Contains(pm.EggGroup2) || pm.EggGroup2 == EggGroup.无))
            {
                return false;
            }
            else if (exceptList.Contains(pm.EggGroup1) || exceptList.Contains(pm.EggGroup2))
            {
                EggGroup eggGroup = default(EggGroup);
                if (exceptList.Contains(pm.EggGroup1))
                {
                    eggGroup = pm.EggGroup2;
                }
                else
                {
                    eggGroup = pm.EggGroup1;
                }

                if (eggGroup != EggGroup.无)
                {
                    List<PokemonData> list = GetPMs(move1, move2, GetEggGroup(eggGroup, exceptList));
                    exceptList.Add(eggGroup);
                    foreach (PokemonData inheritPM in list)
                    {
                        if (CheckMoves(move1, move2, inheritPM, exceptList))
                        {
                            return true;
                        }
                    }
                }
            }
            else
            {
                List<PokemonData> list1 = GetPMs(move1, move2, GetEggGroup(pm.EggGroup1, pm));
                exceptList.Add(pm.EggGroup1);
                if (pm.EggGroup2 != EggGroup.无)
                    exceptList.Add(pm.EggGroup2);

                foreach (PokemonData inheritPM in list1)
                {
                    if (CheckMoves(move1, move2, inheritPM, exceptList))
                    {
                        return true;
                    }
                }

                List<PokemonData> list2 = null;
                if (pm.EggGroup2 != EggGroup.无)
                {
                    list2 = GetPMs(move1, move2, GetEggGroup(pm.EggGroup2, exceptList));
                    foreach (PokemonData inheritPM in list2)
                    {
                        if (CheckMoves(move1, move2, inheritPM, exceptList))
                        {
                            return true;
                        }
                    }
                }

            }
            return false;
        }

        private static bool CanInheritMoves(List<string> MoveDatas, PokemonData pm, List<EggGroup> exceptList)
        {

            if (pm.EggGroup1 == EggGroup.陆上 || pm.EggGroup2 == EggGroup.陆上)
                return true;
            if (exceptList == null)
                exceptList = new List<EggGroup>();

            if (exceptList.Contains(pm.EggGroup1) && (exceptList.Contains(pm.EggGroup2) || pm.EggGroup2 == EggGroup.无))
            {
                return false;
            }
            else if (exceptList.Contains(pm.EggGroup1))
            {
                if (pm.EggGroup2 != EggGroup.无)
                {
                    List<PokemonData> list = GetPMs(MoveDatas, GetEggGroup(pm.EggGroup2, exceptList));
                    exceptList.Add(pm.EggGroup2);
                    foreach (PokemonData inheritPM in list)
                    {
                        if (CheckMoves(MoveDatas, inheritPM, exceptList))
                        {
                            return true;
                        }
                    }
                }
            }
            else if (exceptList.Contains(pm.EggGroup2))
            {
                List<PokemonData> list = GetPMs(MoveDatas, GetEggGroup(pm.EggGroup1, exceptList));
                exceptList.Add(pm.EggGroup1);
                foreach (PokemonData inheritPM in list)
                {
                    if (CheckMoves(MoveDatas, inheritPM, exceptList))
                    {
                        return true;
                    }
                }
            }
            else
            {
                List<PokemonData> list1 = GetPMs(MoveDatas, GetEggGroup(pm.EggGroup1, pm));
                exceptList.Add(pm.EggGroup1);
                if (pm.EggGroup2 != EggGroup.无)
                    exceptList.Add(pm.EggGroup2);

                foreach (PokemonData inheritPM in list1)
                {
                    if (CheckMoves(MoveDatas, inheritPM, exceptList))
                    {
                        return true;
                    }
                }

                List<PokemonData> list2 = null;
                if (pm.EggGroup2 != EggGroup.无)
                {
                    list2 = GetPMs(MoveDatas, GetEggGroup(pm.EggGroup2, exceptList));
                    foreach (PokemonData inheritPM in list2)
                    {
                        if (CheckMoves(MoveDatas, inheritPM, exceptList))
                        {
                            return true;
                        }
                    }
                }

            }
            return false;
        }

        private static bool CheckNijiaMoveDatas(string str1, string str2, PokemonData pm)
        {
            MoveLearnData move1 = default(MoveLearnData);
            MoveLearnData move2 = default(MoveLearnData);
            PokemonData nijia = null;//= BattleData.GetPokemonByNumber(291)[0];
            move1 = nijia.GetMove(str1);
            move2 = nijia.GetMove(str2);
            if (move1.Info == null || move2.Info == null)
                return true;
            int lv1 = 0;
            int lv2 = 0;
            lv1 = Convert.ToInt32(move1.Info);
            lv2 = Convert.ToInt32(move2.Info);
            if (lv1 != lv2)
                return false;
            return true;
        }

        #endregion

    }
}
